package org.noworks.purdue.mapeditor;

import java.awt.Point;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Scanner;

public class XMLHandler {
	private String filename;
	private Scanner in;

	// private final int MAPFILE = 0, LOCATION = 1, PATH = 2;

	public XMLHandler(String filename) {
		super();
		this.setFilename(filename);
		try {
			in = new Scanner(new File(filename));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		}
		in.useDelimiter("\n");
	}

	public XMLHandler(File file) {
		super();
		this.filename = file.getName();
		try {
			in = new Scanner(new File(filename));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public LinkedList<Metapair> nextPair() {
		LinkedList<Metapair> pair = new LinkedList<Metapair>();
		String str = in.next();
		if (str == null)
			return null;
		str = str.replace("\t", "");
		str = str.replace("/", "");
		str = str.replace("<", "");
		str = str.replace(">", "");
		boolean quote = false;
		char[] chars = new char[str.length()];
		for (int idx = 0; idx < str.length(); idx++)
			chars[idx] = str.charAt(idx);
		for (int idx = 0; idx < chars.length; idx++) {
			if (chars[idx] == '\"')
				quote = !quote;
			if (chars[idx] == ' ') {
				if (quote)
					chars[idx] = '/';
			}
		}
		str = "";
		for (char c : chars)
			str += c;
		str = str.replace("\"", "");
		String[] pairs = str.split(" ");
		pair.add(new Metapair("type", pairs[0]));
		for (int idx = 1; idx < pairs.length; idx++) {
			String[] ps = pairs[idx].split("=");
			pair.add(new Metapair(ps[0].replace("/", " "), ps[1].replace("/",
					" ")));
		}
		return pair;
	}

	public boolean hasNext() {
		return in.hasNext();
	}

	public void write(String filename, String imagePath, double scale,
			LinkedList<Location> locations, LinkedList<Path> paths) {
		PrintWriter out = null;
		try {
			out = new PrintWriter(filename);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		}
		String xmlHeader = "";
		out.println(xmlHeader);
		out.println("<mapfile bitmap=\"" + imagePath
				+ "\" scale-feet-per-pixel=\"" + scale + "\">");
		for (int idx = 0; idx < locations.size(); idx++) {
			Location loc = locations.get(idx);
			out.println("\t<location id=\"" + loc.getId() + "\" name=\""
					+ loc.getName() + "\" x=\"" + loc.getPoint().x + "\" y=\""
					+ loc.getPoint().y + "\" />");
		}
		for (int idx = 0; idx < paths.size(); idx++) {
			String dir;
			Path path = paths.get(idx);
			if (path.isDirected())
				dir = "directed";
			else
				dir = "undirected";
			out.println("\t<path idfrom=\"" + path.getIdfrom() + "\" idto=\""
					+ path.getIdto() + "\" type=\"" + dir + "\" />");
		}
		out.println("</mapfile>");
	}

	public static boolean init(String filename, LinkedList<Location> locs,
			LinkedList<Path> paths, String imageFile, double scale) {
		XMLHandler in = new XMLHandler(filename);
		LinkedList<Metapair> list;
		while (in.hasNext()) {
			list = in.nextPair();
			if (list == null)
				break;
			if (list.getFirst().getValue().equalsIgnoreCase("mapfile")) {
				for (int idx = 1; idx < list.size(); idx++) {
					Metapair temp = list.get(idx);
					if (temp.getName().equalsIgnoreCase("bitmap"))
						imageFile = temp.getValue();
					if (temp.getName().equalsIgnoreCase("scale-feet-per-pixel"))
						scale = Double.parseDouble(temp.getValue());
				}
			} else if (list.getFirst().getValue().equalsIgnoreCase("location")) {
				for (int idx = 1; idx < list.size(); idx++) {
					Metapair temp = list.get(idx);
					int x = 0, y = 0, id = 0;
					String name = null;
					if (temp.getName().equalsIgnoreCase("x"))
						x = Integer.parseInt(temp.getValue());
					if (temp.getName().equalsIgnoreCase("y"))
						y = Integer.parseInt(temp.getValue());
					if (temp.getName().equalsIgnoreCase("id"))
						id = Integer.parseInt(temp.getValue());
					if (temp.getName().equalsIgnoreCase("name"))
						name = temp.getValue();
					locs.add(new Location(new Point(x, y), name, id));
				}
			} else if (list.getFirst().getValue().equalsIgnoreCase("path")) {
				for (int idx = 1; idx < list.size(); idx++) {
					Metapair temp = list.get(idx);
					int idto = 0, idfrom = 0;
					boolean dir = false;
					if (temp.getName().equalsIgnoreCase("idto"))
						idto = Integer.parseInt(temp.getValue());
					if (temp.getName().equalsIgnoreCase("idfrom"))
						idfrom = Integer.parseInt(temp.getValue());
					if (temp.getName().equalsIgnoreCase("type"))
						dir = temp.getValue().equalsIgnoreCase("directed");
					paths.add(new Path(idto, idfrom, dir));
				}
			}
		}
		return true;
	}

	public static boolean init(File file, LinkedList<Location> locs,
			LinkedList<Path> paths, String imageFile, double scale) {
		return init(file.getName(), locs, paths, imageFile, scale);
	}

	/**
	 * @return the filename
	 */
	public String getFilename() {
		return filename;
	}

	/**
	 * @param filename
	 *            the filename to set
	 */
	public void setFilename(String filename) {
		this.filename = filename;
	}
}
